use axum::{
    Json, Router,
    extract::{Path, State},
    routing::get,
};
use axum_ifnk_common::{
    app_error,
    prelude::{AppError, Response},
};
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set};

use crate::{
    AppState,
    entities::{prelude::*, users},
    models::CreateUser,
};

type UserModel = users::Model;

/// 用户路由
pub fn routes() -> Router<AppState> {
    Router::<AppState>::new()
        .route("/users", get(list_users).post(create_user))
        .route("/users/{id}", get(get_user_by_id))
}

/// 查询所有用户
#[utoipa::path(
    get,
    path = "/users",
    responses(
        (status = 200, description = "用户列表", body = Response<Vec<UserModel>>)
    ),
    tag = "用户管理"
)]
async fn list_users(State(state): State<AppState>) -> Result<Response<Vec<UserModel>>, AppError> {
    let users = Users::find()
        .all(&state.db)
        .await
        .map_err(|err| AppError::from_error(err).context("查询用户列表失败"))?;

    Ok(Response::success(users))
}

/// 创建用户
#[utoipa::path(
    post,
    path = "/users",
    request_body = CreateUser,
    responses(
        (status = 200, description = "用户创建成功", body = Response<UserModel>)
    ),
    tag = "用户管理"
)]
async fn create_user(
    State(state): State<AppState>,
    Json(payload): Json<CreateUser>,
) -> Result<Response<UserModel>, AppError> {
    if payload.username.trim().is_empty() {
        return Err(app_error!(400, "用户名不能为空"));
    }

    let existing = Users::find()
        .filter(users::Column::Username.eq(&payload.username))
        .one(&state.db)
        .await
        .map_err(|err| AppError::from_error(err).context("检查用户名是否存在失败"))?;

    if existing.is_some() {
        return Err(app_error!(409, "用户名已存在"));
    }

    let active = users::ActiveModel {
        username: Set(payload.username.clone()),
        email: Set(None),
        ..Default::default()
    };

    let model = active
        .insert(&state.db)
        .await
        .map_err(|err| AppError::from_error(err).context("创建用户失败"))?;

    Ok(Response::success(model))
}

/// 根据 ID 查询用户
#[utoipa::path(
    get,
    path = "/users/{id}",
    params(
        ("id" = i32, Path, description = "用户ID")
    ),
    responses(
        (status = 200, description = "用户详情", body = Response<UserModel>),
        (status = 404, description = "用户不存在", body = Response<UserModel>)
    ),
    tag = "用户管理"
)]
async fn get_user_by_id(
    State(state): State<AppState>,
    Path(user_id): Path<i32>,
) -> Result<Response<UserModel>, AppError> {
    let model = Users::find_by_id(user_id)
        .one(&state.db)
        .await
        .map_err(|err| AppError::from_error(err).context("查询用户失败"))?;

    let model = model.ok_or_else(|| app_error!(404, "用户 {} 不存在", user_id))?;

    Ok(Response::success(model))
}
